### Functions Used in Analysis
### Last Revised and commented: 9 June 2016, JBS
### PLACE: Places a vector of members (y) in a space (x). Used in ENLARGE 
### ENLARGE: This is the actual game/model (requires MSM library for rtnorm function)

##########################################################################################

# Place function
# Input: x -- a vector of 0's equal to the length of the desired space
# 		 y -- a vector of the member locations in that space  
# 		 E.g. For a space of length ten x <- rep(0,10), and a membership vector y <- c(2,4,8), function outputs c(0,1,0,1,0,0,0,1,0,0)

place <- function(x,y) {
	x[as.numeric(names(table(y)))] <- table(y)
	return(x)
}

##########################################################################################
### Enlarge function
### Input  -- space is a vector of zeros, length of the space (e.g. 100 unit space represented as rep(0,100))
### 	   -- members is a vector of initial member locations in the space (e.g. c(2,4,50,55,98)) 				
###		   -- sdnmem is the standard deviation of the distribution from which new members are drawn
###		   -- a is the threshold of members required to vote in favor to admit new members. 0.5 represents simple majority.
###		   -- d is the decision-making threshold for policy change in the organization. 0.5 represents simple majority 
### 	   -- sdp is the denominator used to calculate the standard deviation of perceptions of new members. 
###           Larger numbers mean fewer mistakes in perceptions
###		   -- R is the number of rounds. 
### Output -- A vector of final memberships  

 
enlarge <- function(space,members,sdnmem=6,a=0.5,d=0.5,sdp=3,R) {

	# Use Place function to place initial members on the line
	space <- place(space,members)
	
	# Loop over each round
	for (r in 1:R) {
	
		# Determine location of pivotal member for decision-making in organization
		xpiv <- quantile(members, probs = d, type=2)
		
		# Draw the actual position of the new candidate for membership
		# Lower and upper truncate the distribution (best with space of 100) 
		# New members at the very extremes behave strangely
		# If located at the very extreme, it becomes impossible to draw perceptions on one side of the mean
		# rtnorm truncates here so members aren't right at boundary of the space.
		# Set to work with space of 100, would need to be altered if using different space
		nmem <- round(rtnorm(1,mean=mean(members),sd=sdnmem,lower=3,upper=98),digits=0)
		
		# Draw each existing members' perception of the candidate -- A vector equal to the number of existing members
		# Set to work with space of 100, would need to be altered if using different space
		nmemi <- round(rtnorm(length(members),mean=rep(nmem,length(members)),sd=abs(members-nmem)/sdp,lower=1,upper=100),0) 
		
		# replicate current member configuration for each existing member 
		hyp <- rep(list(space),length(members))

		# Create holding bins for hypothetical new memberships for each existing member		
		hypmemlist <- vector("list", length(hyp))

		# For each existing member, create a hypothetical membership vector that reflects what the member perceives 
		# new membership to look like if candidate is admitted
	
		for (i in 1:length(hyp)) {
	
			hyp[[i]][nmemi[i]] <- hyp[[i]][nmemi[i]]+1
		
			hypmemlist[[i]] <- rep(which(hyp[[i]]>=1), hyp[[i]][which(hyp[[i]]>=1)])
		}
	
	# Calculate the new hypothetical pivot for each existing member if the candidate were to be admitted.
    xpiv.hyp <- unlist(lapply(hypmemlist,quantile, probs=d, type=2)) #
            
	# Create vector of votes in favor of admitting candidate 
	# Existing members vote in favor if the distance to current pivot is greater than the distance 
	# to the perceived hypothetical pivot if candidate is admitted.
	votes <- as.numeric(abs(members-xpiv) > abs(members-xpiv.hyp))
	
	# Candidate is admitted if votes in favor cross the decision threshold for admittance
	admit <- ifelse(sum(votes)/length(votes) > a,1,0)

	# If admitted, place the new candidate in the space
	space[nmem] <- ifelse(admit==1,space[nmem]+1,space[nmem])

	# create a vector of new membership
	members <- rep(which(space>=1), space[which(space>=1)])
	}

# function returns the final membership vector after going through all of the rounds.
return(members)

}